package com.scs.application.modules.sys.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.scs.application.core.consts.Const;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.service.IBaseFileService;
import com.scs.application.core.utils.BeanUtils;
import com.scs.application.core.utils.CacheUtils;
import com.scs.application.core.utils.FileUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.sys.dto.FlowDTO;
import com.scs.application.modules.sys.entity.FlowButton;
import com.scs.application.modules.sys.mapper.FlowButtonMapper;
import com.scs.application.modules.sys.service.FlowButtonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 */
@Service
public class FileFlowButtonServiceImpl extends BaseServiceImpl<FlowButtonMapper, FlowButton> implements FlowButtonService, IBaseFileService {
    @Autowired
    private FileFlowServiceImpl fileFlowService;

    @Override
    public Map getByFlowKey(String flowKey) {
        FlowDTO flowDTO = fileFlowService.getFlowDTOByCode(flowKey);
        Map<String, Object> map = new HashMap();
        if (flowDTO == null) {
            throw new BusinessException("未能检索到流程：" + flowKey);
        }
        map.put("flow", flowDTO);
        map.put("flowButtons", flowDTO.getFlowButtons());
        return map;
    }

    @Override
    public boolean removeCascadeById(Serializable id) {
        List<FlowDTO> flowDTOS = fileFlowService.getDTOList();
        for (FlowDTO flowDTO : flowDTOS) {
            if (flowDTO.getFlowButtons() == null || flowDTO.getFlowButtons().isEmpty()) {
                continue;
            }
            CacheUtils.clearCache(CacheUtils.FLOW_BUTTON_CACHE);
            for (FlowDTO.FlowButtonDTO flowButtonDTO : flowDTO.getFlowButtons()) {
                if (id.equals(flowButtonDTO.getId())) {
                    flowDTO.getFlowButtons().remove(flowButtonDTO);
                    String result = JSON.toJSONString(flowDTO, SerializerFeature.PrettyFormat);
                    String fileNameWithPath = Const.DATA_VIEW_FLOW_SRC + flowDTO.getCode() + ".json";
                    FileUtils.writeTxtFile(fileNameWithPath, result);
                    break;
                }
            }
        }
        return true;
    }

    @Override
    public FlowButton getById(Serializable id) {
        List<FlowDTO> flowDTOS = fileFlowService.getDTOList();
        FlowButton flowNode = new FlowButton();
        for (FlowDTO flowDTO : flowDTOS) {
            if (flowDTO.getFlowButtons() == null || flowDTO.getFlowButtons().isEmpty()) {
                continue;
            }
            for (FlowDTO.FlowButtonDTO flowButtonDTO : flowDTO.getFlowButtons()) {
                if (id.equals(flowButtonDTO.getId())) {
                    BeanUtils.copyProperties(flowButtonDTO, flowNode);
                    break;
                }
            }
        }
        return flowNode;
    }

    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        for (Serializable id : idList) {
            removeCascadeById(id);
        }
        return true;
    }

    @Override
    public Page<FlowButton> page(QueryContext context) {
        List<FlowButton> flowButtons = list(context);
        return filePage(context, flowButtons);
    }

    @Override
    public List<FlowButton> getByFlowId(String flowId) {
        QueryContext context = new QueryContext();
        context.setParams(Maps.newHashMap());
        context.getParams().put("flowId", flowId);
        return list(context);
    }

    @Override
    public List<FlowButton> getByFlowCode(String flowCode) {
        QueryContext context = new QueryContext();
        context.setParams(Maps.newHashMap());
        context.getParams().put("flowCode", flowCode);
        return list(context);
    }

    @Override
    public List<FlowButton> list() {
        QueryContext context = new QueryContext();
        return list(context);
    }

    @Override
    public List<FlowButton> list(QueryContext context) {
        List<FlowDTO> flowDTOS = fileFlowService.getDTOList();
        if (flowDTOS == null && flowDTOS.isEmpty()) {
            return null;
        }
        if (context != null && context.getParams() != null && !context.getParams().isEmpty()) {
            String flowId = context.getParams().get("flowId") == null ? "" : context.getParams().get("flowId").toString();
            String flowCode = context.getParams().get("flowCode") == null ? "" : context.getParams().get("flowCode").toString();
            if (StringUtils.isBlank(flowId) && StringUtils.isBlank(flowCode)) {
                return null; //不支持没有传入类型的查询
            }
            Optional<FlowDTO> optFlow = flowDTOS.stream().filter(flow -> {
                if (StringUtils.isNotBlank(flowId)) {
                    return flowId.equalsIgnoreCase(flow.getId());
                } else {
                    return flowCode.equalsIgnoreCase(flow.getCode());
                }
            }).findFirst();
            if (optFlow.isPresent()) {
                List<FlowDTO.FlowButtonDTO> flowNodes = optFlow.get().getFlowButtons();
                if (flowNodes == null || flowNodes.isEmpty()) {
                    return null;
                }
                List<FlowButton> flowButtonList = Lists.newArrayListWithCapacity(flowNodes.size());
                for (FlowDTO.FlowButtonDTO flowButtonDTO : flowNodes) {
                    FlowButton flowButton = new FlowButton();
                    BeanUtils.copyProperties(flowButtonDTO, flowButton);
                    flowButtonList.add(flowButton);
                }
                return flowButtonList.stream().sorted(Comparator.comparing(FlowButton::getSort)).collect(Collectors.toList());
            }
        } else { //获取所有的
            List<FlowButton> flowButtonList = Lists.newArrayList();
            for (FlowDTO flowDTO : flowDTOS) {
                if (flowDTO.getFlowButtons() != null && !flowDTO.getFlowButtons().isEmpty()) {
                    flowDTO.getFlowButtons().forEach(FlowButtonDTO -> {
                        FlowButton flowButton = new FlowButton();
                        BeanUtils.copyProperties(FlowButtonDTO, flowButton);
                        flowButtonList.add(flowButton);
                    });
                }
            }
            return flowButtonList.stream().sorted(Comparator.comparing(FlowButton::getSort)).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public <FlowButton> boolean saveBatch(Class<FlowButton> modelClass, Collection<FlowButton> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean saveOrUpdate(FlowButton flowButton) {
        if (flowButton == null || StringUtils.isEmpty(flowButton.getFlowId())) {
            return false;
        }
        FlowDTO flowDTO = fileFlowService.getFlowDTOById(flowButton.getFlowId());

        if (flowDTO == null) {
            return false;
        }

        File path = new File(Const.DATA_VIEW_FLOW_SRC);
        if (!path.exists()) {
            path.mkdirs();
        }

        FlowDTO.FlowButtonDTO FlowButtonDTO = new FlowDTO.FlowButtonDTO();
        if (flowButton.getId() == null) {
            flowButton.setId(StringUtils.getIdStr());
        }
        if (flowButton.getSort() == null) {
            flowButton.setSort(0);
        }
        BeanUtils.copyProperties(flowButton, FlowButtonDTO);

        flowDTO.getFlowButtons().stream().filter(flow -> flowButton.getCode().equalsIgnoreCase(flow.getCode())
                && !flowButton.getId().equalsIgnoreCase(flow.getId())).findAny().ifPresent(flow -> {
            throw new BusinessException("Key已经存在，请重新命名！");
        });
        flowDTO.getFlowButtons().stream().filter(flow -> flowButton.getId().equalsIgnoreCase(flow.getId()))
                .findAny().ifPresent(flow -> {
            flowDTO.getFlowButtons().remove(flow);
        });

        flowDTO.getFlowButtons().add(FlowButtonDTO);

        String fileNameWithPath = Const.DATA_VIEW_FLOW_SRC + flowDTO.getCode() + ".json";
        String result = JSON.toJSONString(flowDTO, SerializerFeature.PrettyFormat);
        FileUtils.writeTxtFile(fileNameWithPath, result);
        CacheUtils.remove(CacheUtils.FLOW_BUTTON_CACHE, flowDTO.getCode());
        return true;
    }


    @Override
    public Boolean isSupport(Boolean flagProject) {
        return !flagProject;
    }
}
